﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using Newtonsoft.Json;

namespace GJLib
{
    public enum e陰陽 { 陰 = 2, 陽 = 1, none= 0 };
    public class GJR
    {        
        protected static Dictionary<String, int> _干支陰陽 = null;
        static Dictionary<String, List<String>> _地支剋 = null;
        static Dictionary<String, List<String>> _地支受剋 = null;
        protected static Dictionary<String, String> _驛馬;
        protected static Dictionary<String, String> _桃花;
        protected static Dictionary<String, String> _刑;


        protected static Dictionary<String, String> _prevGan = null;
        protected static Dictionary<String, String> _nextGan = null;
        protected static Dictionary<String, String> _prevJi = null;
        protected static Dictionary<String, String> _nextJi = null;

        protected static Dictionary<String, int> _gan2Id = null;
        protected static Dictionary<String, int> _Ji2Id = null;

        protected static Dictionary<int, String> _id2Gan = null;
        protected static Dictionary<int, String> _id2Ji = null;

        protected static Dictionary<String, String> _干支五行 = null;
        protected static Dictionary<String, Dictionary<String, String>> _五行生剋 = null;
        protected static Dictionary<String, Dictionary<String, String>> _五行六親 = null;
        protected static Dictionary<String, String> _天干寄宮 = null;
        protected static Dictionary<String, String> _日干五合 = null;

        protected static Dictionary<String, String> _日德 = null;
        protected static Dictionary<String, String> _支德 = null;
        protected static Dictionary<String, String> _天馬 = null;
        protected static Dictionary<String, String> _支神 = null;
        protected static Dictionary<String, String> _天將五行 = null;


        protected static Dictionary<String,Dictionary<String, String>> _貴人方=null;


        protected static Dictionary<String, List<String>> _月德 = null;
        protected static Dictionary<String, List<String>> _涉害用盤 = null;

        protected static GJR instance = new GJR();
        protected GJR()
        {
            initId();
            initPrevNext();
            LoadJiConquer();
            LoadGanJiInYan();
            LoadHorseFlower();
            Load五行生剋();
            Load干支五行();
            Load天干寄宮();
            Load五行六親();
            LoadGanJiSingle();
            LoadGanJiArray();
            loadGweiRenStart();
            load涉害();
        }

        protected static void load涉害()
        {
            var content = loadContent("SherHai.json");
            var t = JsonConvert.DeserializeObject<Dictionary<String, Dictionary<String, List<String>>>>(content);
            _涉害用盤 = t["涉害用盤"];
        }
        protected void loadGweiRenStart()
        {

            String fileName = @"D:\project\五術\data\relation" + "\\" + "GweiRenStart.json";
            String content = File.ReadAllText(fileName, Encoding.UTF8);
            var t = JsonConvert.DeserializeObject<Dictionary<String, Dictionary<String, String>>>(content);
            _貴人方 = t;            
        }

        public static String 貴人晝占(String dayGan,String method="甲戊庚牛羊")
        {
            if (String.IsNullOrWhiteSpace(method))
                method = "甲戊庚牛羊";
            dayGan = pickFirstWord(dayGan);
            return _貴人方[method + "貴人晝占"][dayGan];
        }
        public static String 貴人夜占(String dayGan, String method = "甲戊庚牛羊")
        {
            if (String.IsNullOrWhiteSpace(method))
                method = "甲戊庚牛羊";
            dayGan = pickFirstWord(dayGan);
            return _貴人方[method + "貴人夜占"][dayGan];
        }
        protected static void LoadGanJiArray()
        {
            var content = loadContent("GanJiArray.json");
            var c = JsonConvert.DeserializeObject<Dictionary<String, Dictionary<String, List<String>>>>(content);
            _月德 = c["月德"];
        }

        protected static void LoadGanJiSingle()
        {
            var c = loadContent("GanJiSingle.json");
            var cc = JsonConvert.DeserializeObject<Dictionary<String, Dictionary<String, String>>>(c);
            _日德 = cc["日德"];
            _支德 = cc["支德"];
            _天馬 = cc["天馬"];
            _支神 = cc["支神"];
            _天將五行 = cc["天將五行"];
        }
        protected void initId()
        {
            String fileName = @"D:\project\五術\data\relation" + "\\" + "GanJi2Id.json";
            String content = File.ReadAllText(fileName, Encoding.UTF8);
            Dictionary<String, Dictionary<String, int>> dd = JsonConvert.DeserializeObject<Dictionary<String, Dictionary<String, int>>>(content);
            _gan2Id = dd["gan2Id"];
            _Ji2Id = dd["ji2Id"];

            fileName = @"D:\project\五術\data\relation" + "\\" + "Id2GanJi.json";
            content = File.ReadAllText(fileName, Encoding.UTF8);
            Dictionary<String, Dictionary<int, String>> dd2 = JsonConvert.DeserializeObject<Dictionary<String, Dictionary<int, String>>>(content);
            _id2Gan = dd2["id2Gan"];
            _id2Ji = dd2["id2Ji"];

        }
        public void initPrevNext()
        {
            String fileName = @"D:\project\五術\data\relation" + "\\" + "prevnext.json";
            String content = File.ReadAllText(fileName, Encoding.UTF8);
            Dictionary<String, Dictionary<String, String>> dd = JsonConvert.DeserializeObject<Dictionary<String, Dictionary<String, String>>>(content);
            _prevGan = dd["prevGan"];
            _nextGan = dd["nextGan"];
            _prevJi = dd["prevJi"];
            _nextJi = dd["nextJi"];
        }


        protected static String loadContent(String fileName)
        {
            if (fileName.EndsWith(".json") == false)
                fileName += ".json";
            fileName = @"D:\project\五術\data\relation\\" + fileName;
            String content = File.ReadAllText(fileName, Encoding.UTF8);
            return content;
        }
        protected static void Load五行生剋()
        {
            String content = loadContent("form5rel.json");
            _五行生剋 = JsonConvert.DeserializeObject<Dictionary<String, Dictionary<String, String>>>(content);
            content = null;
        }
        protected static void Load五行六親()
        {

            String content = loadContent("form5family.json");
            _五行六親 = JsonConvert.DeserializeObject<Dictionary<String, Dictionary<String, String>>>(content);
            content = null;
        }
        protected static void LoadHorseFlower()
        {
            String content = loadContent("horse");
            Dictionary<String, Dictionary<String, String>> c = JsonConvert.DeserializeObject<Dictionary<String, Dictionary<String, String>>>(content);
            _驛馬 = c["驛馬"];
            _桃花 = c["桃花"];
            _刑 = c["刑"];
        }
        protected static void LoadJiConquer()
        {
            String content = loadContent("JiConquer");
            Dictionary<String, Dictionary<String, List<String>>> c = JsonConvert.DeserializeObject<Dictionary<String, Dictionary<String, List<String>>>>(content);
            _地支剋 = c["地支剋"];
            _地支受剋 = c["地支受剋"];
            c.Clear();
        }
        protected static void Load干支五行()
        {
            String content = loadContent("GanJiform.json");
            var c = JsonConvert.DeserializeObject<Dictionary<String, Dictionary<String, String>>>(content);
            _干支五行 = c["干支五行"];

        }
        protected static void Load天干寄宮()
        {
            String content = loadContent("GanToJi.json");
            var c = JsonConvert.DeserializeObject<Dictionary<String, Dictionary<String, String>>>(content);
            _天干寄宮 = c["天干寄宮"];
            _日干五合 = c["日干五合"];
        }
        public static List<String> 所剋(String ji)
        {

            return _地支剋[ji];
        }
        public static List<String> 受剋(String ji)
        {

            return _地支受剋[ji];
        }

        protected static void LoadGanJiInYan()
        {
            String content = loadContent("GanJiInYan");
            _干支陰陽 = JsonConvert.DeserializeObject<Dictionary<String, int>>(content);
            content = "";
        }

        public static int 孟仲季(String n)
        {
            int v = _干支陰陽[n];
            v = v % 3;
            return v;
        }
        public static e陰陽 陰陽(String n)
        {
            if (n.Length > 1)
                n = n.Substring(0, 1);
            int v = _干支陰陽[n];
            if (v % 2 > 0)
                return e陰陽.陽;
            return e陰陽.陰;
        }
        public static String 驛馬(String n)
        {
            if (String.IsNullOrWhiteSpace(n)) return "";
            n = pickLastWord(n);
            return _驛馬[n];
        }
        public static String 桃花(String n)
        {
            if (String.IsNullOrWhiteSpace(n)) return "";
            n = pickLastWord(n);
            return _桃花[n];
        }
        public static int ganId(String gan)
        {
            gan = pickFirstWord(gan);
            return _gan2Id[gan];
        }

        public static int JiId(String ji)
        {
            ji = pickLastWord(ji);
            return _Ji2Id[ji];
        }
        public static String Id2Gan(int id)
        {
            return _id2Gan[(id + 10) % 10];
        }
        public static String Id2Ji(int id)
        {
            return _id2Ji[(id + 12) % 12];
        }
        public static String prevGan(String gan)
        {
            return _prevGan[gan];
        }
        public static String prevJi(String ji)
        {
            return _prevJi[ji];
        }
        public static String checkGJ(String gj)
        {
            String g = pickFirstWord(gj);
            String j = pickLastWord(gj);
            if ("己已".Contains(j))
                j = "巳";
            if ("戍".Contains(j))
                j = "戌";

            return g + j;
        }
        public static String nextGan(String gan)
        {
            return _nextGan[gan];
        }
        public static String nextJi(String ji)
        {
            return _nextJi[ji];
        }
        public static int A剋B(String A, String B)
        {
            String f5_1 = _干支五行[A];
            String f5_2 = _干支五行[B];
            if (_五行生剋[f5_1][f5_2].Equals("死"))
            {
                return 1;
            }
            if (_五行生剋[f5_1][f5_2].Equals("囚"))
            {
                return -1;
            }
            return 0;
        }
        public static String 天干寄宮(String gan)
        {
            gan = pickFirstWord(gan);
            return _天干寄宮[gan];
        }
        public static String 五合(String gan)
        {
            gan = pickFirstWord(gan);
            return _日干五合[gan];
        }
        public static bool 對沖(String a, String b)
        {
            int a1 = _Ji2Id[a];
            int b1 = _Ji2Id[b];
            if (a1 == b1)
                return false;
            if ((a1 - b1) % 6 == 0)
                return true;
            return false;
        }
        public static String 三合(String ji)
        {
            if (String.IsNullOrWhiteSpace(ji)) return "";
            ji = pickLastWord(ji);
            List<String> result = new List<string>();
            result.Add(_id2Ji[(_Ji2Id[ji] + 4) % 12]);
            result.Add(_id2Ji[(_Ji2Id[ji] + 8) % 12]);
            StringBuilder sb = new StringBuilder();
            foreach (var s in result)
                sb.Append(s);
            return sb.ToString();
        }
        public static String 六合(String ji)
        {
            if (String.IsNullOrWhiteSpace(ji)) return "";
            ji = pickLastWord(ji);
            int id = (15 - JiId(ji))%12;
            return Id2Ji(id);

        }
        public static String 三合前(String ji)
        {
            return _id2Ji[(_Ji2Id[ji] + 4) % 12];
        }

        public static string 位移(string gj, int p)
        {
            if (_gan2Id.ContainsKey(gj))
            {
                int id = (_gan2Id[gj] + 10 + p) % 10;
                return _id2Gan[id];
            }
            else
            {
                int id = (_Ji2Id[gj] + 12 + p) % 12;
                return _id2Ji[id];
            }
        }

        public static string A刑B(string p)
        {
            if (String.IsNullOrWhiteSpace(p)) return "";
            p = pickLastWord(p);
            return _刑[p];
        }

        public static string 沖(string ji)
        {
            if (String.IsNullOrWhiteSpace(ji)) return "";
            ji = pickLastWord(ji);
            return GJR.位移(ji, 6);
        }
        public static String 六親AofB(String A, String B)
        {
            String f5_1 = _干支五行[A];
            String f5_2 = _干支五行[B];
            return _五行六親[f5_2][f5_1];
        }

        public static bool isJi(string ji)
        {
            return _Ji2Id.ContainsKey(ji);
        }
        /*
         回傳  JI 
         */
        public static String 旬首(String ganji)
        {
            if (String.IsNullOrWhiteSpace(ganji))
                return "";
            int gId = ganId(ganji.Substring(0, 1));
            int jId = JiId(ganji.Substring(1, 1));
            int off = jId - gId;
            if (off < 0)
                off += 12;
            return Id2Ji(off + 1);
        }
        public static String 空亡(String ganji,e陰陽  inyan = e陰陽.none)
        {
            if (String.IsNullOrWhiteSpace(ganji)) return "";
            int gId = ganId(ganji.Substring(0, 1));
            int jId = JiId(ganji.Substring(1, 1));
            int off = jId - gId;
            if (off <= 0)
                off += 12;
            List<String> result = new List<string>();
            StringBuilder sb = new StringBuilder();
            if (inyan == e陰陽.none)
            {
                sb.Append(_id2Ji[off - 1]);
                sb.Append(_id2Ji[off]);
            }
            if (inyan == e陰陽.陽)
            {
                sb.Append(_id2Ji[off - 1]);                
            }
            if (inyan == e陰陽.陰)
            {
                sb.Append(_id2Ji[off]);
            }
            return sb.ToString();
        }
        public static String 支破(String ji)
        {
            if (String.IsNullOrWhiteSpace(ji)) return "";
            ji = pickLastWord(ji);
            //陰向前+3
            //陽向後-3
            int id = JiId(ji);
            if (陰陽(ji)== e陰陽.陽)
            {
                id = id - 3;
            }
            else
            {
                id = id + 3;
            }
            return Id2Ji(id % 12);

        }
        public static String 支害(String ji)
        {
            if (String.IsNullOrWhiteSpace(ji)) return "";
            int id = JiId(ji);
            return Id2Ji((13 - id - 6 + 12) % 12);
        }
        public static String 六十甲子fromId(int id)
        {
            int g = id % 10;
            int j = id % 12;
            return Id2Gan(g) + Id2Ji(j);
        }
        public static String 六十甲子fromId(int id, int off1, int off2)
        {
            int g = (id + off1) % 10;
            int j = (id + off2) % 12;
            return Id2Gan(g) + Id2Ji(j);
        }
        public static int 六十甲子(String gj)
        {
            int g1, j1;
            g1 = ganId(gj.Substring(0, 1));
            if (g1 == 0)
                g1 = 10;
            j1 = JiId(gj.Substring(1, 1));
            int off = (12 + j1 - g1) % 12;
            //超前代表後退幾次 ~~
            int start1 = 1 + off;
            int step = (12 - off) / 2;
            int of = (j1 - start1 + 12) % 12;
            int pos = step * 10 + of + 1;
            return pos;

        }
        protected static String[] 女命行年干 = { "癸", "壬", "辛", "庚", "己", "戊", "丁", "丙", "乙", "甲" };
        protected static String[] 女命行年支 = { "酉", "申", "未", "午", "巳", "辰", "卯", "寅", "丑", "子", "亥", "戌" };

        public static String 女命行年(int year)
        {
            int g = year % 10;
            int j = year % 12;
            return 女命行年干[g] + 女命行年支[j];
        }
        public static String 行年(String 本命, String 太歲, bool male)
        {
            int b = 六十甲子(本命);
            int now = 六十甲子(太歲);
            int off = (now + 60 - b) % 60;
            if (male)
                return 六十甲子fromId(off + 3);
            return 女命行年(off + 1);
        }
        public static String 日德(String gan)
        {
            if (String.IsNullOrWhiteSpace(gan)) return "";
            gan = pickFirstWord(gan);
            return _日德[gan];
        }
        public static String 支德(String ji)
        {
            if (String.IsNullOrWhiteSpace(ji)) return "";
            ji = pickLastWord(ji);
            return _支德[ji];
        }
        public static String pickFirstWord(String gan)
        {
            if (gan.Length > 1)
                gan = gan.Substring(0, 1);
            return gan;
        }

        public static String pickLastWord(String ji)
        {
            if (ji.Length > 1)
                ji = ji.Substring(ji.Length - 1, 1);
            return ji;
        }
        public static String 月德(String ji)
        {
            if (String.IsNullOrWhiteSpace(ji)) return "";
            ji = pickLastWord(ji);
            StringBuilder sb = new StringBuilder();
            foreach (var s in _月德[ji])
            {
                sb.Append(s);
            }
            return sb.ToString();
        }

        public static String 旬遁(String ganji, String gan)
        {
            String start = 旬首(ganji);
            int gi = ganId(gan);
            int ji = JiId(start);
            return Id2Ji(ji + gi - 1);
        }
        public static String 丁馬(String ganji)
        {
            if (String.IsNullOrWhiteSpace(ganji)) return "";
            return 旬遁(ganji, "丁");
        }

        public static String 旬丁(String ganji)
        {
            if (String.IsNullOrWhiteSpace(ganji)) return "";
            return 旬遁(ganji, "丁");
        }
        public static String 旬庚(String ganji)
        {
            if (String.IsNullOrWhiteSpace(ganji)) return "";
            return 旬遁(ganji, "庚");
        }
        public static String 旬辛(String ganji)
        {
            if (String.IsNullOrWhiteSpace(ganji)) return "";
            return 旬遁(ganji, "辛");
        }
        public static String 旬癸(String ganji)
        {
            if (String.IsNullOrWhiteSpace(ganji)) return "";
            return 旬遁(ganji, "癸");
        }
        public static String 天馬(String ji)
        {
            if (String.IsNullOrWhiteSpace(ji)) return "";
            ji = pickLastWord(ji);
            return _天馬[ji];
        }

        public static string 支神(string ji)
        {
            if (String.IsNullOrWhiteSpace(ji)) return "";
            ji = pickLastWord(ji);
            return _支神[ji];
        }
        public static Dictionary<String, String> 天將五行()
        {
            return _天將五行;
        }
        public static bool 日干寄宮於支(string 日干支)
        {
            return 天干寄宮(pickFirstWord(日干支)).Contains(pickLastWord(日干支));
        }
        public static int 歷數歸於本家(String from, String to, bool 剋or被剋)
        {
            int k = 0;
            int invK = 0;
            do
            {
                List<String> content = _涉害用盤[from];
                foreach (String ji in content)
                {
                    int v = A剋B(to, ji);
                    if (v > 0)
                        k++;
                    if (v < 0)
                        invK++;
                }
                if (from == to)
                {
                    break;
                }
                from = nextJi(from);
            } while (true);
            if (剋or被剋)
                return k;
            else
                return invK;
        }

        public static string 五虎遁(string p, string 月干支)
        {
            月干支 = GJR.pickLastWord(月干支);
            int off = GJR.JiId(月干支) - GJR.JiId("寅");
            if (off < 0)
                off += 12;
            p = GJR.pickFirstWord(p);
            String startGan="";
            if ("甲己".Contains(p))
                startGan = "丙";
            if ("乙庚".Contains(p))
                startGan = "戊";
            if ("丙辛".Contains(p))
                startGan = "庚";
            if ("丁壬".Contains(p))
                startGan = "壬";
            if ("戊癸".Contains(p))
                startGan = "甲";

            int id = (GJR.ganId(startGan) + off) % 10;
            return GJR.Id2Gan(id) + 月干支;
        }

        public static string 五鼠遁(string 日干, string 時干支)
        {
            時干支 = GJR.pickLastWord(時干支);
            int off = GJR.JiId(時干支) - GJR.JiId("子");
            if (off < 0)
                off += 12;
            日干 = GJR.pickFirstWord(日干);
            String startGan = "";
            if ("甲己".Contains(日干))
                startGan = "甲";
            if ("乙庚".Contains(日干))
                startGan = "丙";
            if ("丙辛".Contains(日干))
                startGan = "戊";
            if ("丁壬".Contains(日干))
                startGan = "庚";
            if ("戊癸".Contains(日干))
                startGan = "壬";
            
            int id = (GJR.ganId(startGan) + off) % 10;
            return GJR.Id2Gan(id) + 時干支;
        }

        protected static String[] _地支 = { "子", "丑", "寅", "卯", "辰", "巳", "午", "未", "申", "酉", "戌", "亥" };

        public  static string[] 地支()
        {
            return _地支;
        }
    }
}
